#region File header
// Project: Server, File: MainForm.cs
// Namespace: SharpWars, Class: MainForm
// Path: C:\Developer\Projects\Uczelnia\SharpWind.Core.Network\Server, 
// Author: Sebastian Haba (sho@gisz.net.pl)
// Code lines: 183, Size of file: 5,24 KB
// Creation date: 2007-01-04 17:16
// Last modified: 2007-01-04 18:32
#endregion

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Xml.Serialization;
using System.IO;
using SharpWars.Core.Network;

namespace SharpWars
{
	public partial class MainForm : Form
	{
		private Options options = new Options();

		private Server server = new Server();

		public MainForm()
		{
			InitializeComponent();

			this.FormClosing += new FormClosingEventHandler( OnClosing );

			this.server.Exception += new ExceptionEventHandler( OnException );
			this.server.Started += new StatusEventHandler( OnServerStarted );
			this.server.Stoped += new StatusEventHandler( OnServerStoped );
			this.server.PlayerJoin += new PlayerEventHandler( OnPlayerJoin );
			this.server.PlayerDisconnected += new PlayerEventHandler( OnPlayerDisconnected );
			this.server.LogMessage += new LogEventHandler( OnLog );
			this.server.Statistics.Update += new EventHandler( OnStatisticsUpdate );

			string[] commands = Enum.GetNames( typeof( Command ) );
			Array.Sort( commands );

			foreach( string name in commands )
			{
				ListViewItem item = new ListViewItem( name );
				ListViewItem.ListViewSubItem sub1 = new ListViewItem.ListViewSubItem( item, "0" );
				ListViewItem.ListViewSubItem sub2 = new ListViewItem.ListViewSubItem( item, "0" );
				ListViewItem.ListViewSubItem sub3 = new ListViewItem.ListViewSubItem( item, "0" );
				ListViewItem.ListViewSubItem sub4 = new ListViewItem.ListViewSubItem( item, "0" );

				item.SubItems.AddRange( new ListViewItem.ListViewSubItem[] { sub1, sub2, sub3, sub4 } );

				this.detailedStatistics.Items.Add( item );
			}
		}

		private void OnStatisticsUpdate( object sender, EventArgs e )
		{
			if( InvokeRequired )
			{
				EventHandler eventHandler = new EventHandler( OnStatisticsUpdate );
				Invoke( eventHandler );
			}
			else
			{
				this.totalPacketsSend.Text = this.server.Statistics.Total.SendCount.ToString();
				this.totalReceivedPackets.Text = this.server.Statistics.Total.ReceivedCount.ToString();
				this.totalBytesSend.Text = this.server.Statistics.Total.SendBytes.ToString();
				this.totalReceivedBytes.Text = this.server.Statistics.Total.ReceivedBytes.ToString();

				foreach( string name in Enum.GetNames( typeof( Command ) ) )
				{
					foreach( ListViewItem item in this.detailedStatistics.Items )
					{
						if( item.Text == name )
						{
							item.SubItems[ 1 ].Text = this.server.Statistics.Packets[ name ].SendCount.ToString();
							item.SubItems[ 2 ].Text = this.server.Statistics.Packets[ name ].ReceivedCount.ToString();
							item.SubItems[ 3 ].Text = this.server.Statistics.Packets[ name ].SendBytes.ToString();
							item.SubItems[ 4 ].Text = this.server.Statistics.Packets[ name ].ReceivedBytes.ToString();
							break;
						}
					}
				}
			}
		}

		private void OnLog( object sender, string message )
		{
			Log( message );
		}

		private void OnClosing( object sender, FormClosingEventArgs e )
		{
			if( this.server.IsStarted )
			{
				this.server.Stop();
			}
		}

		private void OnPlayerJoin( object sender, PlayerEventArgs e )
		{
			Log( "Client " + e.Name + " joined." );
			AddClientToList( CreateClient( e ) );
		}

		private Player CreateClient( PlayerEventArgs e )
		{
			Player client = new Player();
			client.PlayerID = e.PlayerID;
			client.Name = e.Name;
			client.Ready = e.Ready;

			return client;
		}

		private void OnPlayerDisconnected( object sender, PlayerEventArgs e )
		{
			Log( "Client " + e.Name + " disconnected." );
			RemoveClientFromList( CreateClient( e ) );
		}

		private delegate void ClientOperationDelegate( Player client );

		private void AddClientToList( Player client )
		{
			ListViewItem name = new ListViewItem( client.Name );
			name.SubItems.Add( new ListViewItem.ListViewSubItem( name, client.PlayerID.ToString() ) );
			name.SubItems.Add( new ListViewItem.ListViewSubItem( name, client.Ready.ToString() ) );

			if( playersListView.InvokeRequired )
			{
				ClientOperationDelegate addClient = new ClientOperationDelegate( AddClientToList );
				Invoke( addClient, new object[] { client } );
			}
			else
			{
				this.playersListView.Items.Add( name );
			}
		}

		private void RemoveClientFromList( Player client )
		{
			if( playersListView.InvokeRequired )
			{
				ClientOperationDelegate removeClient = new ClientOperationDelegate( RemoveClientFromList );
				Invoke( removeClient, new object[] { client } );
			}
			else
			{
				foreach( ListViewItem item in this.playersListView.Items )
				{
					if( item.Text == client.Name )
					{
						this.playersListView.Items.Remove( item );
						break;
					}
				}
			}
		}

		private void OnServerStarted( object sender, StatusEventArgs e )
		{
			Log( "Server start listening on " + e.IP + ":" + e.Port.ToString() );

			this.stopToolStripMenuItem.Enabled = true;
			this.stopMenuItem.Enabled = true;
			this.startToolStripMenuItem.Enabled = false;
			this.ipComboBox.Enabled = false;
			this.portTextBox.Enabled = false;
			this.maxConnectionsTextBox.Enabled = false;
			this.passwordTextBox.Enabled = false;
			this.nameTextBox.Enabled = false;
			this.startMenuItem.Enabled = false;
		}

		private void OnServerStoped( object sender, StatusEventArgs e )
		{
			ClearClientsList();

			this.stopToolStripMenuItem.Enabled = false;
			this.stopMenuItem.Enabled = false;
			this.startToolStripMenuItem.Enabled = true;
			this.ipComboBox.Enabled = true;
			this.portTextBox.Enabled = true;
			this.maxConnectionsTextBox.Enabled = true;
			this.passwordTextBox.Enabled = true;
			this.nameTextBox.Enabled = true;
			this.startMenuItem.Enabled = true;


		}

		private void OnException( object sender, ExceptionEventArgs e )
		{
			Log( "Exception: " + e.Message );
		}

		private delegate void ClearClientsDelegate();

		private void ClearClientsList()
		{
			if( this.playersListView.InvokeRequired )
			{
				ClearClientsDelegate clearClients = new ClearClientsDelegate( ClearClientsList );
				Invoke( clearClients );
			}
			else
			{
				this.playersListView.Items.Clear();
			}
		}

		private void OnResize( object sender, EventArgs e )
		{
			if( WindowState == FormWindowState.Minimized )
			{
				Hide();
			}
		}

		private void OnNotifyIconDoubleClick( object sender, EventArgs e )
		{
			Show();
			WindowState = FormWindowState.Normal;
			this.showMenuItem.Text = "Hide";
		}

		private void OnExitClick( object sender, EventArgs e )
		{
			Application.Exit();
		}

		private void OnLoad( object sender, EventArgs e )
		{
			foreach( IPAddress address in Dns.GetHostAddresses( Dns.GetHostName() ) )
			{
				this.ipComboBox.Items.Add( address.ToString() );
			}

#if( DEBUG )

			this.ipComboBox.Items.Add( "127.0.0.1" );

#endif

			this.ipComboBox.SelectedIndex = 0;
		}

		private void OnSaveClick( object sender, EventArgs e )
		{

		}

		private void OnStartClick( object sender, EventArgs e )
		{
			this.server.Start( this.ipComboBox.SelectedItem as string, int.Parse( this.portTextBox.Text ) );
		}

		private void OnStopClick( object sender, EventArgs e )
		{
			this.server.Stop();
		}

		private delegate void LogDelegate( string message );

		private void Log( string message )
		{
			if( this.logsRichTextBox.InvokeRequired )
			{
				LogDelegate ld = new LogDelegate( Log );
				Invoke( ld, new object[] { message } );
			}
			else
			{

				this.logsRichTextBox.Text += "[" + DateTime.Now.ToLongTimeString() + "." + DateTime.Now.Millisecond + "]: " + message + "\n";
				logsRichTextBox.Select( logsRichTextBox.TextLength - 2, logsRichTextBox.TextLength - 1 );
				logsRichTextBox.ScrollToCaret();
			} // else
		}

		private void OnShowClick( object sender, EventArgs e )
		{
			if( this.showMenuItem.Text == "Show" )
			{
				Show();
				WindowState = FormWindowState.Normal;
				this.showMenuItem.Text = "Hide";
			}
			else
			{
				WindowState = FormWindowState.Minimized;
				this.showMenuItem.Text = "Show";
			}
		}

		private void OnKickClick( object sender, EventArgs e )
		{
			if( this.playersListView.SelectedItems.Count > 0 )
			{
				string name = this.playersListView.SelectedItems[ 0 ].Text;
				int playerID = int.Parse( this.playersListView.SelectedItems[ 0 ].SubItems[ 1 ].Text );

				this.server.Kick( playerID );

				Player player = new Player();
				player.Name = name;
				player.PlayerID = playerID;
				RemoveClientFromList( player );
			}
		}
	}
}